#include "Options.h"
#include <map>
#include <stdexcept>
using std::map;
using std::string;

#ifdef _MSC_VER
#pragma warning(disable:4996) // for strcpy
#endif

namespace dsth {
OptionVal::OptionVal() {
}

OptionVal::OptionVal(int val) : intVal(val) {
}

OptionVal::OptionVal(unsigned short val) : usVal(val) {
}

OptionVal::OptionVal(bool val) : boolVal(val) {
}

OptionVal::OptionVal(const char* val) {
    ::strcpy(strVal, val);
}

class NULLOptionKeyException : public std::logic_error {
public:
    NULLOptionKeyException() : std::logic_error("An Null Key is used") {
    }
};

const int map_init_size = 7; // modify me if init map changed
std::map<string, OptionVal>::value_type map_init_data[map_init_size] = {
    map<string, OptionVal>::value_type("ChannelBufferLength", 1024),
    map<string, OptionVal>::value_type("ChannelBufferPrepend", 8),
    map<string, OptionVal>::value_type("ReactorTimeoutUsec", 10000),
    map<string, OptionVal>::value_type("ConnectRetryTime", 3),
    // for windows self connect
    map<string, OptionVal>::value_type("SelfConnectionEable", true),
    map<string, OptionVal>::value_type("SelfConnectionHost", "127.0.0.1"),
    map<string, OptionVal>::value_type("SelfConnectionBeginPort", static_cast<unsigned short>(29900))
};

static map<string, OptionVal> gOptions(map_init_data, map_init_data + map_init_size);
void SetOption(const char* key, OptionVal val) {
    if (key == NULL) {
        throw NULLOptionKeyException();
    }
    gOptions[key] = val;
}

OptionVal GetOption(const char* option) {
    if (option == NULL) {
        throw NULLOptionKeyException();
    }
    return gOptions[option];
}

} // namespace
